/*
 * App.js is the heart and soul of Qype S60 WRT widget:
 * qype object is the core that loads everything else
 * 
 */

qype = Object.extend(qype, {
	
	/* engine object takes care of UI functionality:
	 * It shows and hides the views when needed,
	 * and stores the view history for back button
	 * To find out more, check Engine.js
	 */
    engine: undefined, 
	
	/* screen object is used specifically for 
	 * recognizing screen mode (landscape/portrait)
	 * and screen size
	 * To find out more, check Screen.js
	 */
    screen: undefined,  
	
	// This is just a dummy for GPS features
    soGeolocation: undefined,

	// Okay, this is where it all begins after HTML is loaded
    onload: function() {
		// First of all, we hide softkeys 
		// to release maximum space for UI
        if(window.menu) {
            window.menu.hideSoftkeys();
        }

		// Continue to the actual init
        this.init();
    },

	// onresize() captures the onresize event from browser window
    onresize: function() {
		// Screen object takes care of the rest (Screen.js)
        this.screen.resize();
    },

	// init is executed immediately when the app starts (through onload)
    init: function() {
		
		// Set custom click handler for all buttons on UI
		// See wrtpressurize.js for more info
        util.pressurizeAll("button");
		
		// Initialize the objects, explained before
        this.screen = new Screen();
        this.engine = new Engine();

		// util.el is a common function to getElementById
		// Defined in util.js
        this.loadingStatus = util.el("loadingStatus");
		this.locationStatus = util.el("locationStatus");

        /* Now, it's time to register needed views for the engine.
         * 
         * View is a common class to take care of dynamic content
         * in the UI. In short, engine calls view class's builder
         * when the view is about to be displayed.
         *  
		 * Giving undefined as the value registers the view 
		 * as of type plain View, having no dynamic data (i.e. Loading View)
		 *
		 * qype.views.<name> are defined in view-specific js-files
		 * (see, for example, PlacesView.js)
		 * 
		 * View class is defined in View.js
		 */
        this.engine.registerViews({
            "loadingView": undefined, 
			"locationView": qype.views.LocationView, 
            "categoriesView": qype.views.CategoriesView,
            "placesView": qype.views.PlacesView,
            "placeView": qype.views.PlaceView,
            "mapView": qype.views.MapView
        })

		// Initialize screen size info
		this.onresize();

        // Activate first view (= Loading/splash) 
		// and do not add it to the navigation
        // stack; we don't want user to be able to
		// hit back button in main view to return
		// to the loading screen
        this.engine.activateView("loadingView", {
            excludeFromNavigation: true
        });

        // To make the user experience a little bit smoother,
		// we call next step (update location) through a small
		// delay
        var self = this;
        setTimeout(function() {
	        self.setInitialLocation();
        }, 1000)		
    },
	
	// Initial location is not being fetched from GPS for 
	// better user-experience; it may take some time to receive
	// fix from satellites, and we don't want this to happen
	// when user starts the app.
	//
	// Instead, the last known location is used until user manually 
	// refreshes GPS location (button in Places View)
	setInitialLocation: function() {
		// Util.log is used just for writing progress 
		// to console.log in Web Inspector (util.js)
		util.log("{app} Using fixed location");
		
		// Set status text in Loading View
        this.setLoadingStatus("Let's first take you to London...");
		
		var latitude, longitude = undefined;
		
		/* Here we are using widget storage to store as key-value pairs
		 * the last known GPS location. 
		 * If none exists and/or this is the first time the app is used,
		 * default values are used instead
		 */
		try { 
			latitude = window.widget.preferenceForKey("latitude") ;
			longitude = window.widget.preferenceForKey("longitude") ;
		} catch (e) {
			// Do nothing; this is just for safe if widget object
			// is not supported by the browser for some reason	
		}
		
		// If no stored values were available, use default
		if(!latitude || !longitude) { 
			latitude = 51.51091;  // London
			longitude =  -0.13654;  // London
		}
		
		// Now, because no actual GPS is being used,
		// we are calling the location update callback
		// directly; coordinates are given as parameters
		this.onUpdateLocationSuccess({
            coords : {
                latitude : latitude,  
                longitude : longitude,
                altitude : 0,
                accuracy : 0,
                altitudeAccuracy : 0,
                heading : 0,
                speed : 0
            },
            timestamp : Date
        });
		
	},
	
	/* This is called when user presses 'Refresh GPS' button
	 * in Places View
	 */
	refreshLocation: function() {
		
		// Reset location status text
		this.setLocationStatus("Loading..");
		
		// Set the Location View to become visible	
		this.engine.activateView("locationView");
		
		// Launch GPS location update, with given
		// callback to handle the results
		this.updateLocation(
            this.onUpdateLocationSuccess.bind(this),
            this.onUpdateLocationFailure.bind(this)
        );
	},

	// Writes loading status updates to Loading View
    setLoadingStatus: function(txt) {
        this.loadingStatus.innerHTML = txt;
    },

	// Writes location status updates to Loading View
    setLocationStatus: function(txt) {
        this.locationStatus.innerHTML = txt;
    },

	/* Really simple function to take care of GPS location update
	 */
    updateLocation: function(onSuccess, onError) {
		
		// Set status text in Location View
        this.setLocationStatus("Acquiring location...");

		/* ***************************
		   PLACE HERE CODE SNIPPET 13.1
		  ****************************/

		// Initialize Platform Service object for GPS
        this.soGeolocation = this.soGeolocation || nokia.device.load("geolocation");

		/* ***************************
		   PLACE HERE CODE SNIPPET 13.2
		  ****************************/

		// Set parameters for the service object
        var opts = {
            timeout: 30000,
            maximumAge: 20000
        };

		/* ***************************
		   PLACE HERE CODE SNIPPET 13.3
		  ****************************/

		// Initialize location getting (and set the callbacks & parameters)
        try {
            this.soGeolocation.getCurrentPosition(onSuccess, onError, opts);
        }
        catch (e) {
			// In case something goes wrong, write to log & status
            util.log("{qype.updateLocation} error fetching the position: " + Object.toJSON(e));
            this.setLocationStatus("Error fetching the location! (" + Object.toJSON(e) + ")");
        }
    },

	/* onUpdateLocationSuccess is called when GPS receives a location
	 * It stores the received location to widget storage (as the last known position)
	 * and calls engine startup in Engine.js
	 */
    onUpdateLocationSuccess: function(position) {
		// Necessary updates to Web Inspector log and to location status
        util.log("{app} Got location!");
        this.setLocationStatus("Found: lat " + position.coords.latitude + ", lon " + position.coords.longitude);
		
		// Store the coordinates as key-value pairs to widget storage
		/*try {
			window.widget.setPreferenceForKey(position.coords.latitude.toString(), "latitude");
			window.widget.setPreferenceForKey(position.coords.longitude.toString(), "longitude");
		} catch (e) {
			// Do nothing;	
		}*/

        // Slight delay to shoow the current status message 
		// before moving on
        var self = this;
        setTimeout(function() {
            self.engine.startup(position);
        }, 1200)
    },

	/* In case the GPS location fetching fails, onUpdateLocationFailure
	 * is called instead of onUpdateLocationSuccess
	 */
    onUpdateLocationFailure: function(e) {
		// Update web inspector log and location status
        util.log("{qype.init} error fetching the location");
        this.setLocationStatus("Error fetching the location (event handler)! (" + ((e) ? Object.toJSON(e) : '') + ")");
    }
});

